package cn.xzqwjw.taskmanager.service.impl;

import cn.xzqwjw.taskmanager.common.customEnum.ResponseCodeEnum;
import cn.xzqwjw.taskmanager.common.exception.CustomException;
import cn.xzqwjw.taskmanager.domain.pojo.SysConfig;
import cn.xzqwjw.taskmanager.domain.vo.ResponseVo;
import cn.xzqwjw.taskmanager.domain.vo.UploadConfigVo;
import cn.xzqwjw.taskmanager.repository.SysConfigMapper;
import cn.xzqwjw.taskmanager.service.SysConfigService;
import cn.xzqwjw.taskmanager.utils.ConvertUtil;
import cn.xzqwjw.taskmanager.utils.JsonUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author rush
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig>
    implements SysConfigService {

  @Override
  public String add(SysConfig sysConfig) {
    if (validLabel(sysConfig.getLabel(), 0)) {
      throw new CustomException(ResponseCodeEnum.UNPROCESSABLE_ENTITY);
    }
    if (save(sysConfig)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_CREATED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_INSERT);
    }
  }

  @Override
  public String addBatch(List<SysConfig> list) {
    if (saveBatch(list)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_CREATED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_INSERT);
    }
  }

  @Override
  public String delById(int id) {
    // 先得到是否是系统预定值
    QueryWrapper<SysConfig> wrapper = new QueryWrapper<>();
    wrapper.select("flag_system").eq("id", id);
    Map<String, Object> resultMap = getMap(wrapper);
    if (MapUtils.isEmpty(resultMap)) {
      if ((Boolean) resultMap.get("flag_system")) {
        throw new CustomException(ResponseCodeEnum.ERROR_DELETE);
      }
    }
    // 不是系统预定值，可以删除
    if (removeById(id)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_DELETED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_DELETE);
    }
  }

  @Override
  public String modifyAll(SysConfig sysConfig) {
    if (validLabel(sysConfig.getLabel(), sysConfig.getId())) {
      throw new CustomException(ResponseCodeEnum.UNPROCESSABLE_ENTITY);
    }
    if (updateById(sysConfig)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_UPDATED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_UPDATE);
    }
  }

  /**
   * 修改值或者备注
   */
  @Override
  public String patchByParams(int id, String paramsJson) {
    Map<?, ?> map = JsonUtil.json2Obj(paramsJson, Map.class);
    String value, remark;
    String fieldValue = "Value";
    if (Objects.nonNull(map.get(fieldValue))) {
      value = (String) map.get(fieldValue);
    } else {
      value = "";
    }
    String fieldRemark = "Remark";
    if (Objects.nonNull(map.get(fieldRemark))) {
      remark = (String) map.get(fieldRemark);
    } else {
      remark = "";
    }
    if (!StringUtils.hasLength(value) && !StringUtils.hasLength(remark)) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    UpdateWrapper<SysConfig> wrapper = new UpdateWrapper<>();
    wrapper.eq("id", id);
    if (StringUtils.hasText(value)) {
      wrapper.set("value", value);
    }
    if (StringUtils.hasText(remark)) {
      wrapper.set("remark", remark);
    }
    if (update(wrapper)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_UPDATED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_PATCH);
    }
  }

  @Override
  public String queryById(int id) {
    SysConfig sysConfig = getById(id);
    if (!Objects.isNull(sysConfig)) {
      return JsonUtil.obj2Json(ResponseVo.success(sysConfig));
    } else {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
  }

  @Override
  public String listAll(String tag) {
    if (StringUtils.hasText(tag)) {
      QueryWrapper<SysConfig> wrapper = new QueryWrapper<>();
      wrapper.eq("tag", tag);
      return JsonUtil.obj2Json(ResponseVo.success(list(wrapper)));
    } else {
      return JsonUtil.obj2Json(ResponseVo.success(list()));
    }
  }

  @Override
  public String checkLabel(String label, int id) {
    Map<String, String> returnMap = new HashMap<>(16);
    returnMap.put("IsAdded", String.valueOf(validLabel(label, id)));
    return JsonUtil.obj2Json(ResponseVo.success(returnMap));
  }

  // ==================== 私有方法 ====================

  @Override
  public UploadConfigVo getUploadConfigDefault() {
    // 如果没有查到数据，返回的结果：
    // listMaps() 得到的是一个Size=0的List<Map<String, Object>>，
    // getMap()得到的是null
    // 如果有结果，getMap()得到的是第一条数据
    UploadConfigVo configVo = new UploadConfigVo();
    QueryWrapper<SysConfig> wrapper = new QueryWrapper<>();
    wrapper.select("label", "value").eq("tag", "Upload");
    List<Map<String, Object>> resultList = listMaps(wrapper);
    if (CollectionUtils.isEmpty(resultList)) {
      return configVo;
    }
    // 执行到这里，说明数据库中已设置了值
    configVo.setPathRootPhysics(getValueByLabel(resultList, "PathRootPhysics"));
    configVo.setAllowedExt(getValueByLabel(resultList, "AllowedExt"));
    configVo.setAllowedExtImg(getValueByLabel(resultList, "AllowedExtImg"));
    configVo.setAllowedSizeImg(ConvertUtil.str2Long(getValueByLabel(resultList, "AllowedSizeImg")));
    configVo.setAllowedSizeDoc(ConvertUtil.str2Long(getValueByLabel(resultList, "AllowedSizeDoc")));
    configVo.setAllowedSizeZip(ConvertUtil.str2Long(getValueByLabel(resultList, "AllowedSizeZip")));
    configVo.setAllowedSizeMedia(ConvertUtil.str2Long(getValueByLabel(resultList, "AllowedSizeMedia")));
    configVo.setFlagWaterMarkTxt(Boolean.parseBoolean(getValueByLabel(resultList, "FlagWaterMarkTxt")));
    configVo.setWaterMarkTxtString(getValueByLabel(resultList, "WaterMarkTxtString"));
    configVo.setWaterMarkTxtFont(getValueByLabel(resultList, "WaterMarkTxtFont"));
    configVo.setWaterMarkTxtSize(Float.parseFloat(getValueByLabel(resultList, "WaterMarkTxtSize")));
    configVo.setWaterMarkTxtColor(getValueByLabel(resultList, "WaterMarkTxtColor"));
    configVo.setFlagWaterMarkImg(Boolean.parseBoolean(getValueByLabel(resultList, "FlagWaterMarkImg")));
    configVo.setWaterMarkImagePath(getValueByLabel(resultList, "WaterMarkImagePath"));
    configVo.setWaterMarkMarginTop(ConvertUtil.str2Int(getValueByLabel(resultList, "WaterMarkMarginTop")));
    configVo.setWaterMarkMarginRight(ConvertUtil.str2Int(getValueByLabel(resultList, "WaterMarkMarginRight")));
    configVo.setWaterMarkMarginBottom(ConvertUtil.str2Int(getValueByLabel(resultList, "WaterMarkMarginBottom")));
    configVo.setWaterMarkMarginLeft(ConvertUtil.str2Int(getValueByLabel(resultList, "WaterMarkMarginLeft")));
    String transparentString = getValueByLabel(resultList, "WaterMarkTransparent");
    if ("".equals(transparentString) || ConvertUtil.isWrongFloatString(transparentString)) {
      configVo.setWaterMarkTransparent(0.4F);
    } else {
      configVo.setWaterMarkTransparent(ConvertUtil.str2Float(transparentString));
    }
    configVo.setFlagThumb(Boolean.parseBoolean(getValueByLabel(resultList, "FlagThumb")));
    String compressString = getValueByLabel(resultList, "CompressRatio");
    if ("".equals(compressString) || ConvertUtil.isWrongDoubleString(compressString)) {
      configVo.setCompressRatio(0.9);
    } else {
      configVo.setCompressRatio(ConvertUtil.str2Double(compressString));
    }
    return configVo;
  }

  private String getValueByLabel(List<Map<String, Object>> resultList, String label) {
    String resultString = "";
    String key;
    for (Map<String, Object> map : resultList) {
      key = String.valueOf(map.get("label"));
      if (key.equals(label)) {
        resultString = String.valueOf(map.get("value"));
        break;
      }
    }
    return "null".equals(resultString) ? "" : resultString;
  }

  /**
   * 判断设置名称是否已添加
   *
   * @param label 设置名称
   * @return 是否已添加
   */
  private boolean validLabel(String label, int id) {
    QueryWrapper<SysConfig> wrapper = new QueryWrapper<>();
    if (id > 0) {
      wrapper.eq("label", label).ne("id", id);
    } else {
      wrapper.eq("label", label);
    }
    return getOne(wrapper, false) != null;
  }

}
